Enterprise Objects Framework Release 1.1 Copyright ã1995 by NeXT Computer, Inc.  All Rights Reserved.

EODatabase

Inherits From:	NSObject

Declared In:	eoaccess/EODatabase.h

Class Description

An EODatabase represents a database, and consequently encapsulates all of the characteristics of that database, including its name, model, and connection (login) information. An EODatabase also uniques and makes snapshots of enterprise objects fetched from the server. Uniquing of fetched objects reduces memory consumption and allows all objects in a client application to immediately see changes when the uniqued enterprise object is updated or refetched. Snapshots are used by EODatabaseContext objects during updates; see the EODatabaseContext class specification for details on updating with snapshots. General information on uniquing is presented below.

An EODatabase uses one or more EODatabaseContext objects to manage transactions in the server. Each such object forms a separate transaction scope, and is in effect a separate logical user to the server. An EODatabaseContext uses one or more EODatabaseChannel objects to manage data operations (insert, update, delete, and fetch). Adaptors may support a limited number of contexts per database or channels per context, but an application is guaranteed at least one of each.

The EODatabase, EODatabaseContext, and EODatabaseChannel classes form the database level of the Enterprise Objects Framework, which operates in terms of enterprise objects. The database level is a client of the adaptor level, which operates in terms of dictionary objects and which is defined by the adaptor classes: EOAdaptor, EOAdaptorContext, and EOAdaptorChannel. The objects of the database level create their own corresponding adaptor objects, so you needn't ever use adaptor API when you're working at the database level. You do have access to the adaptor objects, however, should you need a feature available only in the adaptor level.

Connecting to the Server

An EODatabase doesn't keep a connection dictionary of its own as an EOAdaptor does. You normally create an EODatabase with an existing EOModel object, which in turn is usually defined with the EOModeler application (see the EOModel class specification for information on loading a model file). The EOModel contains information on which adaptor bundle it needs and also contains a connection dictionary. The following code excerpt shows one way you might set up a suite of database objects, given a model that's already been loaded:

EOModel *myModel;    /* Assume this exists. */
EODatabase *myDatabase;
EODatabaseContext *myContext;
EODatabaseChannel *myChannel;
EOAdaptor *myAdaptor;

myDatabase = [[EODatabase alloc] initWithModel:myModel];
myContext =  [[EODatabaseContext alloc] initWithDatabase:myDatabase];
myChannel =  [[EODatabaseChannel alloc]
     initWithDatabaseContext:myContext];

myAdaptor = [myDatabase adaptor];

if ([myAdaptor hasValidConnectionDictionary] == NO &&
    [myAdaptor runLoginPanelAndValidateConnectionDictionary] == NO) {
    /* Handle user canceling the panel... */
}

if ([myChannel openChannel] == NO) {
    /* Handle error... */
}

The section beginning with the invocation of hasValidConnectionDictionary makes sure that the EODatabase's adaptor has the proper information needed to log in to the server. If the connection dictionary doesn't have valid information (for example, it's common to leave the user name and password unspecified in the model file), runLoginPanelAndValidateConnectionDictionary is invoked to allow the user to enter the necessary connection information. The invocation of openChannel at the end of the excerpt causes the application to form a connection to the database.

Uniquing

EODatabase can unique each object fetched by its channels, so that for any primary key value and entity there's only one enterprise object in memory (if any). Whenever a database channel fetches the data for a row, it checks with its database object to see if an enterprise object for that row's primary key has already been recorded. If so, it hands the row data to the enterprise object and returns the object; if not, it creates a new enterprise object for the fetched row, has the database object unique it, and then returns the unique enterprise object.

The enterprise objects uniqued by an EODatabase, along with cached snapshots of their values, form the global view of data for nearly every other part of the application. Uniqued enterprise objects suffer from no synchronization problems with regard to any other objects that may be examining them. This global view is only overridden locally by EODatabaseContexts, which form their own snapshots as they make changes during a transactionÐthe changes they make to uniqued enterprise objects are still immediately visible to the entire application. When a database context commits its top-level transaction, it reconciles all changed snapshots with the global view of the database object, so that other database contexts (except those with open transactions) immediately use the new snapshots as well.

Your application can explicitly handle the uniquing and snapshotting of enterprise objects, causing them to be uniqued before they would automatically be uniqued, or even removing them from the set of uniqued objects. To unique an enterprise object, you send the EODatabase a recordObject:primaryKey:snapshot: message. To remove it from the uniquing tables it you send forgetObject: or forgetAllObjects. To get the unique enterprise object for a given primary key, you use objectForPrimaryKey:entity:.

Instance Variables

None declared in this class.

Method Types

Initializing new instances	- initWithAdaptor:
- initWithModel:

Getting the adaptor	- adaptor

Getting the database contexts	- contexts

Checking connection status	- hasOpenChannels

Uniquing/snapshotting	- setUniquesObjects:
- uniquesObjects
- setKeepsSnapshots:
- keepsSnapshots
- forgetAllObjects:
+ forgetObject:
- forgetObject:
- objectForPrimaryKey:entity:
- recordObject:primaryKey:snapshot:
- snapshotForObject:

Class Methods

forgetObject:

+ (void)forgetObject:anEO

Sends forgetObject: to every EODatabase instance in the application with anEO as the argument. This causes each EODatabase to remove anEO from its uniquing tables and to destroy any snapshot associated with it.

See also:  - uniquesObjects, - keepsSnapshots

Instance Methods

adaptor

- (EOAdaptor *)adaptor

Returns the EOAdaptor used by the EODatabase for communication with the database server. Your application can interact directly with the EOAdaptor, but should avoid altering its state (for example, by starting a transaction with one of its adaptor contexts).

contexts

- (NSArray *)contexts

Returns the EODatabaseContexts managing transaction scopes for the EODatabase.

forgetAllObjects

- (void)forgetAllObjects

If the EODatabase uniques objects, removes all objects from the receiver's uniquing tables. If the EODatabase keeps snapshots, also destroys all snapshots.

See also:  - uniquesObjects, - keepsSnapshots

forgetObject:

- (void)forgetObject:anEO

If the EODatabase uniques objects, removes anEO from the receiver's uniquing tables, and if the EODatabase keeps snapshots also destroys the snapshot recorded under anEO's primary key. An EODatabase invokes this method whenever an enterprise object uniqued by it is deallocated.

See also:  - uniquesObjects, - keepsSnapshots

hasOpenChannels

- (BOOL)hasOpenChannels

Returns YES if the database's adaptor has any open EOAdaptorChannels, NO otherwise.

See also:  - hasOpenChannels (EOAdaptor), - openChannel (EODatabaseChannel)

initWithAdaptor:

- initWithAdaptor:(EOAdaptor *)anAdaptor

Initializes a newly allocated EODatabase with anAdaptor as its adaptor and returns self. You should never associate more than one EODatabase with a given adaptor. In general, use initWithModel:, which automatically selects the adaptor. This is the designated initializer for the EODatabase class.

initWithModel:

- initWithModel:(EOModel *)aModel

Initializes a newly allocated EODatabase by creating an instance of EOAdaptor named in aModel and invoking initWithAdaptor:. Returns self.

See also:  + adaptorWithModel: (EOAdaptor), - adaptorName (EOModel)

keepsSnapshots

- (BOOL)keepsSnapshots

Returns YES if the EODatabase keeps snapshots for all enterprise objects fetched by its database channels, NO if not. The default behavior is to keep snapshots.

If an EODatabase doesn't keep snapshots then none of the uniquing-snapshotting methods affect snapshots at all; for example, recordObject:primaryKey:snapshot: won't record a snapshot (though it may record the object). See the EODatabaseContext class specification for information on how snapshots are used.

objectForPrimaryKey:entity:

- objectForPrimaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity

Returns the unique enterprise object for aKey and anEntity, or nil if one can't be found.

See also:  - primaryKeyForRow: (EOEntity), - uniquesObjects

recordObject:primaryKey:snapshot:

- (void)recordObject:anEO
primaryKey:(NSDictionary *)aKey
snapshot:(NSDictionary *)aSnapshot

If the EODatabase uniques objects, records anEO under aKey so that it becomes the sole instance related to that key. If a record with the same key is fetched later, its data is applied to the unique instance, which is then returned to the requestor. Raises NSInvalidArgumentException when uniquing if anEO or aKey is nil.

If the EODatabase keeps snapshots, also records aSnapshot under aKey. Raises NSInvalidArgumentException when making a snapshot if aSnapshot is nil and anEO isn't a fault (see the EOFault class specification for information on faults).

There may already be a unique instance recorded for anEO's key, so you shouldn't expect that the object you pass in to this method can be shared. To get the unique enterprise object created for anEO, use objectForPrimaryKey:entity:.

See also:  - primaryKeyForRow: (EOEntity), - uniquesObjects, - keepsSnapshots

setKeepsSnapshots:

- (void)setKeepsSnapshots:(BOOL)flag

Sets according to flag whether the EODatabase keeps snapshots for fetched enterprise objects. If flag is NO, also deletes any existing snapshots. Raises NSInvalidArgumentException if the EODatabase has any open channels.

An EODatabase must be set to keep snapshots to allow updates across transactions. See the EODatabaseContext class specification for information on snapshots and updating.

See also:  - hasOpenChannels

setUniquesObjects:

- (void)setUniquesObjects:(BOOL)flag

Sets according to flag whether the EODatabase uniques fetched enterprise objects. If flag is NO, also forgets any uniqued enterprise objects. Raises NSInvalidArgumentException if the EODatabase has any open channels.

See also:  - hasOpenChannels, - forgetObject:

snapshotForObject:

- (NSDictionary *)snapshotForObject:anEO

Returns the snapshot associated with anEO's id, if there is one; otherwise returns nil.

See also:  - keepsSnapshots

uniquesObjects

- (BOOL)uniquesObjects

Returns YES if the EODatabase uniques fetched enterprise objects, NO if not. The default behavior is to unique objects.

If an EODatabase doesn't unique objects then none of the uniquing-snapshotting methods affect the uniquing tables at all; for example, recordObject:primaryKey:snapshot: won't record the object (though it may record a snapshot).